#ifndef INP_FERTROT_H
#define INP_FERTROT_H

//#include "stdafx.h"
using namespace std;
class Inp_fertrot
{
	static Par_Maps par_fert_props;
	static int Flag_par_fert_props;
	
	int get_timing_by_type(map<string,double> plotprops,string temporal_id)
	{
		int dec=0;
		double nminfert;
		nminfert=plotprops[temporal_id+"NO3"]+plotprops[temporal_id+"NH4"]+plotprops[temporal_id+"NH2"];
		if (nminfert==0) ;
		else if (nminfert<60) dec++;
		else if ((nminfert>=60)&&(nminfert<200)) dec=dec+2;
		else if (nminfert>=200) dec=dec+3;
		
		if(plotprops[temporal_id+"pig_slurrys_deep_application"]>0) dec++;
		if(plotprops[temporal_id+"cattle_slurrys_deep_application"]>0) dec++;
		if(plotprops[temporal_id+"poultry_slurrys_deep_application"]>0) dec++;
		if(plotprops[temporal_id+"pig_slurrys_surface_applied"]>0) dec++;
		if(plotprops[temporal_id+"cattle_slurrys_surface_applied"]>0) dec++;
		if(plotprops[temporal_id+"poultry_slurrys_surface_applied"]>0) dec++;
		if(plotprops[temporal_id+"pig_solid_manure"]>0) dec++;
		if(plotprops[temporal_id+"cattle_solid_manure"]>0) dec++;
		if(plotprops[temporal_id+"other_solid_manure"]>0) dec++;
		return dec;
	}
	time_intervall set_a_new_entry_from_plotprops(time_intervall apply_int,map<string,double> &plotprops,double nminfert)
	{
		timestamp apply_time2;
		
		map <string,double> Fert_values;
		
		apply_int.set_move(30);
		Fert_values["N[kg/ha]"]=nminfert;
		Fert_values["site_id"]=plotprops["plot_id"];
		Fert_values["fert_id"]= -999999;
		Fert_values["Dry_matter_content[t/t]"]=this->ptr->get_nodata();
		Fert_values["C_content[t/t]"]=this->ptr->get_nodata();
		Fert_values["N_content[kg/t]"]=this->ptr->get_nodata();
		Fert_values["amount[tFM/ha]"]=this->ptr->get_nodata();
		Fert_values["C[t/ha]"]=this->ptr->get_nodata();
		this->ptr->set_insert_or_replace_entry(apply_int, Fert_values);
		return apply_int;
	}
	int set_new_entrys_from_plotprops(map<string,double> &plotprops,timestamp apply_time,string temporal_id,double step)
	{
			// This function writes fertrot for a given temporal_id (string; example: recent) which stands for an application 
			//	period
			double nminfert;
			time_intervall apply_int;
			timestamp apply_time2;
			int dec=0;
			int x;
			// build the first apply_int
			apply_time2=apply_time;
			apply_time2.set_add_days(1);
			apply_int.set(apply_time,apply_time2);
			//anorganic fertilizers are assumed to be ALL Kalkammonsalpeter
			nminfert=plotprops[temporal_id+"_NO3"]+plotprops[temporal_id+"_NH4"];
			if (nminfert==0) ;
			else if (nminfert<60) dec++;
			else if ((nminfert>=60)&&(nminfert<200)) dec=dec+2;
			else if (nminfert>=200) dec=dec+3;
			if(nminfert>0) nminfert=nminfert/dec;
			
			for(x=0;x<dec;x++)
			{
				apply_int= set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	0;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//urease
			nminfert=plotprops[temporal_id+"_NH2"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	3;
				update_all_fert_props_from_N(apply_int,fertilizercode);
				
			}
			//pigslurry_deep
			nminfert=plotprops[temporal_id+"_pig_slurrys_deep_application"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	21;
				update_all_fert_props_from_N(apply_int,fertilizercode);
				
			}
			//cattleslurry_deep
			nminfert=plotprops[temporal_id+"_cattle_slurrys_deep_application"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	24;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//cattleslurry_deep
			nminfert=plotprops[temporal_id+"_poultry_slurrys_deep_application"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	 24;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//pig_slurrys_surface_applied
			nminfert=plotprops[temporal_id+"_pig_slurrys_surface_applied"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	21;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//cattle_slurrys_surface_applied
			nminfert=plotprops[temporal_id+"_cattle_slurrys_surface_applied"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	  24;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//poultry_slurrys_surface_applied
			nminfert=plotprops[temporal_id+"_poultry_slurrys_surface_applied"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	 26;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//pig_solid_manure
			nminfert=plotprops[temporal_id+"_pig_solid_manure"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	  31;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			//cattle_solid_manure
			nminfert=plotprops[temporal_id+"_cattle_solid_manure"];
			if(nminfert>0) {
				apply_int=set_a_new_entry_from_plotprops(apply_int,plotprops,nminfert);
				int fertilizercode=	  31;
				update_all_fert_props_from_N(apply_int,fertilizercode);
			}
			return 0;
		}
	int update_all_fert_props_from_N(time_intervall apply_int,int fertid)
		{
			// given the N Input form ha we want to calculate/ get all the other stuff
					
			double drymatterc;
			double fertamount;
			double N_content;
			double C_content;
			double C,N;
			unsigned int row;
			
			// find the row
			row=this->ptr->get_row_from_time_intervall(apply_int);
			if (row>this->ptr->get_size()){
				err::err3("Inp_fertrot::update_all_fert_props_from_N: The specific row_entry that fits to time_int is not in time");
			
			}
			// fert_id
			this->ptr->set_val("fert_id",row,fertid);
			
			drymatterc=this->ptr->get_val("Dry_matter_content[t/t]",row);
			if (drymatterc<0){
				drymatterc=par_fert_props.get_val("Dry_matter_content[t/t]",fertid);
				this->ptr->set_val("Dry_matter_content[t/t]",row,drymatterc);
			}
			
			N_content=this->ptr->get_val("N_content[kg/t]",row);
			if (N_content<0){
				N_content=par_fert_props.get_val("N_content[kg/t]",fertid);
				this->ptr->set_val("N_content[kg/t]",row,N_content);
			}
				
			C_content=this->ptr->get_val("C_content[t/t]",row);
			if (C_content<0){
				C_content=par_fert_props.get_val("C_content[t/t]",fertid);
				this->ptr->set_val("C_content[t/t]",row,C_content);
			}
			
			fertamount=this->ptr->get_val("amount[tFM/ha]",row);
			if(fertamount<0){
				fertamount=this->ptr->get_val("N[kg/ha]",row)/N_content/drymatterc;
				this->ptr->set_val("amount[tFM/ha]",row,fertamount);
			}
			//N [kg/ha]
			N=this->ptr->get_val("N[kg/ha]",row);
			if(N<0){
				N=this->ptr->get_val("amount[tFM/ha]",row)*drymatterc*N_content;
				this->ptr->set_val("N[kg/ha]",row,N);
			}
			//C [t/ha]
			C=this->ptr->get_val("C[t/ha]",row);
			if(C<0){
				C=fertamount*drymatterc*C_content;
				this->ptr->set_val("C[t/ha]",row,C);
			}
			return 0;
		}
public:
	tempmap <string,double> *ptr;
	vector <string> variables;
	time_intervall timint_mod;
	string root;
	string name;
	string suffix;
	string time_horizon_id;
	map<string,int> CONT;


	Inp_fertrot(
		map<string,int> ICONT,
		vector <string> ivariables,
		string intervall_mode,
		int multipli,
		double dur,
		string itime_horizon_id,
		time_intervall itimint_mod,
		string iroot,
		string iname,
		string isuffix
		)
	{
	// initialization of variables
		CONT=ICONT;
		variables=ivariables;
		time_horizon_id=itime_horizon_id;
		timint_mod=itimint_mod;
		root=iroot;
		name=iname;
		suffix=isuffix;
	// Reading of Parameterfiles
		ptr=new tempmap <string,double> (0,-999999,intervall_mode,multipli,dur);
		if (Flag_par_fert_props==0){
			par_fert_props.read_Par_Maps("./par/","Par_Fert_Props",".par");
			Flag_par_fert_props=1;
		}
	}
	~Inp_fertrot()
	{
		delete (ptr);
	}
	int set_input(
		list2d *fertlist,
		Inp_croprot *croprot,
		string sitename,
		map<string,double> &plotprops
		)
		{
			if (CONT["READ_FROM_FILE"]!=0){
				if(set_input_from_file(timint_mod)){
					if(set_input_from_list2D(fertlist,this,croprot,timint_mod,sitename)){
						if(set_input_from_plotprops(plotprops,fertlist,croprot,timint_mod, sitename)){
							return 1;
						}
						else{
							this->ptr->print_in_file_simple_style_with_mydate(root,name,suffix);
							return 0;
						}
					}
				}
			}
			else{
				if(set_input_from_list2D(fertlist,this,croprot,timint_mod,sitename)){
					if(set_input_from_plotprops(plotprops,fertlist,croprot,timint_mod, sitename)){
						return 1;
					}
					else{
						this->ptr->print_in_file_simple_style_with_mydate(root,name,suffix);
						return 0;
					}
				}
			}
			this->ptr->print_in_file_simple_style_with_mydate(root,name,suffix);
			return 0;
		}
	int set_input_from_file(time_intervall timint_mod)
	{
		if(this->ptr->set_read_from_file(root,name,suffix,this->ptr->intervall_mode,this->ptr->multipli,
			this->ptr->dur)){
				return 1;
		}
		variables=this->ptr->get_valkeys();
		return 0;
	}
	int set_input_from_list2D(list2d *fertlist,Inp_fertrot *fertrot,Inp_croprot *croprot,time_intervall timint_mod,
		string sitename)
	{
		IN_read_fertrotation infert(fertlist,fertrot,croprot,timint_mod,sitename);
		if (read_fertrotation::read_fertrot(infert)) return 1;
		return 0;

	}
	int set_input_from_plotprops(map<string,double> &plotprops,list2d *fertlist,
		Inp_croprot *croprot,time_intervall timint_mode,string sitename)
	{
		//1. No fertilisation before march (3. Month
		//2. Below 60 kg/per year 1 time fertilizer application in mid april
		//3. Above 200 kg per/year 3 times fertilizer application april/may/june
		//4. Between 60 and 200 kg per year 2 times fertilizer application april/may
		//5. Winter_crop --Early application 3. 4,5
		//6. Summer crop late application --> mid 4. mid 5, early 6
		//7. Perennial 1(4) 2(4,6) 3 (3,5,7)
		//7. Was, wenn 3.4.5 Monat nicht im Zeitraum oder erst im Zeitraum ende?
			// --> wenn erster der 4. dann WC zwei Applikationen; Summer normal
			//--> wenn erster der 5. dann WC eine Applikation  
		//8. Each_organic_compound in plotprops stands for a separate application
		timestamp start,end;
		timestamp fert_time;
		map <string,double> Fert_values;
		unsigned int rowid;
		int timing_by_type;
		int crop_typ;
		timestamp apply_time;
		string temporal_id;
		int dec;
		int count;
		
	    // get the plotprop time intervall
		start.set((int) plotprops["startyear"],(int) plotprops["startmon"],plotprops["startday"]);
		end.set((int) plotprops["endyear"],(int) plotprops["endmon"],plotprops["endday"]);

		// getting the recent crop row which is the first one seeded after start
		// rowid is the returned indice of (croprot->ptr)
		if(croprot->ptr->get_next_upeq_valid_data_midpoint(start,rowid,"crop_id"));
		// if this one does not exist we look for the one seeded before start
		else if (croprot->ptr->get_next_loweq_valid_data_midpoint(start,rowid,"crop_id")) {
			err::err3("Inp_fertrot::set_input_from_plotprops: Could not derive any cropgrowthintervall that fits to the start_end intervall of plotprops");
			return 1;
		}
		// setting the keys of maps fertrot and 
		this->ptr->set_key(fertlist->get_key());
		this->ptr->set_delete_key("year");
		this->ptr->set_delete_key("mon");
		this->ptr->set_delete_key("day");
		this->ptr->set_key("C[t/ha]");
		this->ptr->set_key("N[kg/ha]");
                vector <string> keys=fertlist->get_key();
		// setting the keys of Fert_values(map<string,double>)and assigning nodata
		Basics_map::set_key(Fert_values,keys,this->ptr->get_nodata());
		// Three cases wintercrop, summercrop, perennial
		crop_typ=(int)croprot->ptr->get_val("crop_typ",rowid);
		// get_timing_by_type from_types_of_fertilizer
		timing_by_type=get_timing_by_type(plotprops,"recent");
		temporal_id="recent";
		dec=0;
		apply_time.set(croprot->ptr->get_time_intervall(rowid).get_end().get_year(),2,15.0);
		switch (crop_typ)
		{
			case 0: // Winter crop
				apply_time.set(croprot->ptr->get_time_intervall(rowid).get_end().get_year(),2,15.0);
				set_new_entrys_from_plotprops(plotprops,apply_time,temporal_id,25);
				//The same story for adjacent and following year
				apply_time.set(croprot->ptr->get_time_intervall(rowid).get_end().get_year()-1,2,15.0);
				set_new_entrys_from_plotprops(plotprops,apply_time,temporal_id,25);
				
				break;
				
			case 1: // summer crop
					apply_time.set(croprot->ptr->get_time_intervall(rowid).get_end().get_year(),3,15.0);
					set_new_entrys_from_plotprops(plotprops,apply_time,temporal_id,25);
					apply_time.set(croprot->ptr->get_time_intervall(rowid).get_end().get_year()-1,3,15.0);
					set_new_entrys_from_plotprops(plotprops,apply_time,temporal_id,25);
				break;
			case 3: // perennial crop
					apply_time.set(croprot->ptr->get_time_intervall(0).get_start().get_year	(),2,15.0);
					count=1;
					do{
					
						set_new_entrys_from_plotprops(plotprops,apply_time,temporal_id,30);
						apply_time.set(croprot->ptr->get_time_intervall(0).get_start().get_year	()+count,2,15.0);
						count++;
					}
					while(apply_time<croprot->ptr->get_end());
				break;
			default:
					err::err3("Inp_fertrot::Strange cropid");
				break;
		}
		return 0;
	}
};
#endif